package org.aj.common.web.file.util;

import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author jcj
 * description 处理图片相关的工具方法
 * date  2021/4/19 17:46
 */
public class ImageUtil {




    /**
     * 原生
     * description  图片压缩
     * @param bytes 字节数组  非空
     * @param maxPixel  转换的像素  默认为1024              （如：maxPixel=720） 非空
     * @param photoSuffix  图片的后缀 例如 jpg 默认为jpg 目前支持 [JPG, jpg, bmp, BMP, gif, GIF, WBMP, png, PNG, jpeg, wbmp, JPEG]
     *                     通过ImageIO.getWriterFormatNames() 限定，目前jdk的版本1.8 ,所升级了jdk 查看是否有变化
     * @return: byte[]
     * @author: jcj
     * date : 2021/3/2 20:11
     */
    public static byte[] transformer(byte[] bytes,Integer maxPixel,String photoSuffix) throws Exception {

        if(null == bytes || bytes.length == 0  ){
            throw new IllegalArgumentException("bytes must not null and not empty");
        }

        if(null == maxPixel){
            maxPixel = 1024;
        }

        if(StringUtils.isBlank(photoSuffix)){
            photoSuffix = "jpg";
        }
        //判断当前是否是支持的格式

        if (!isSupportedOutputFormat(photoSuffix)) {
            throw new IllegalArgumentException(
                    "Specified format is not supported: " + photoSuffix+",supported:"+getSupportedOutputFormats().toString()
            );
        }

        //校验图片像素
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);

        BufferedImage read = ImageIO.read(bis);


        // 生成图片转化对象
        AffineTransform transform = new AffineTransform();
        // 通过缓存读入缓存对象

        int imageWidth = read.getWidth();//原图片的高度
        int imageHeight = read.getHeight();//原图片的宽度
        int changeWidth = 0;//压缩后图片的高度
        int changeHeight = 0;//压缩后图片的宽度
        double scale = 0;// 定义小图片和原图片比例
        if (maxPixel != 0) {
            if (imageWidth > imageHeight) {
                changeWidth = maxPixel;
                scale = (double) changeWidth / (double) imageWidth;
                changeHeight = (int) (imageHeight * scale);
            } else {
                changeHeight = maxPixel;
                scale = (double) changeHeight / (double) imageHeight;
                changeWidth = (int) (imageWidth * scale);
            }
        }
        // 生成转换比例
        transform.setToScale(scale, scale);


        BufferedImage basll = new BufferedImage(changeWidth,changeHeight,getTypeInt(photoSuffix));

        Graphics2D gd2 = basll.createGraphics();
        gd2.drawImage(read, transform,null);
        gd2.dispose();

        //创建一个内存输出流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        //输出缩小图片
        ImageIO.write(basll, photoSuffix,bos);

        return bos.toByteArray();


    /*
        目前发现下面这种做法很容易出现 java.awt.image.ImagingOpException: Unable to transform src image 异常故采用上面这种方式
     // 生成转换操作对象
        AffineTransformOp transOp = new AffineTransformOp(transform, null);
        //生成压缩图片缓冲对象
        BufferedImage basll = new BufferedImage(changeWidth, changeHeight,
                BufferedImage.TYPE_3BYTE_BGR);
        //生成缩小图片
        transOp.filter(read, basll);

        //创建一个内存输出流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        //输出缩小图片
        ImageIO.write(basll, photoSuffix,bos);

        return bos.toByteArray();*/

    }


    /**
     * 获取int类型的图片类型
     *
     * @return 图片类型
     * @see BufferedImage#TYPE_INT_ARGB
     * @see BufferedImage#TYPE_INT_RGB
     */
    private static int getTypeInt(String photoSuffix) {
        if("png".equalsIgnoreCase(photoSuffix)){
            return BufferedImage.TYPE_INT_ARGB;
        }
        return BufferedImage.TYPE_INT_RGB;
    }



            //得到当前支持的压缩的图片格式 后缀
    public static List<String> getSupportedOutputFormats() {
        String[] formats = ImageIO.getWriterFormatNames();

        if (formats == null) {
            return Collections.emptyList();
        } else {
            return Arrays.asList(formats);
        }
    }


    /**
     * Returns whether a specified format is supported for output.
     *
     * @param format	The format to check whether it is supported or not.
     * @return			{@code true} if the format is supported, {@code false}
     * 					otherwise.
     */
    public static boolean isSupportedOutputFormat(String format)
    {


        for (String supportedFormat : getSupportedOutputFormats())
        {
            if (supportedFormat.equals(format))
            {
                return true;
            }
        }

        return false;
    }



}
